home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / PPM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-27  |  13.6 KB  |  580 lines

  1. /****************************************************************************
  2. *                ppm.c
  3. *
  4. *  This module contains the code to read and write the PPM file format.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. * Original patch copyright 1994 Tim Rowley
  23. * Updated for POV 3.0 by Chris Cason, Jan '95.
  24. *
  25. *****************************************************************************/
  26.  
  27. /****************************************************************************
  28. *  The format is as follows:
  29. *
  30. *  (header:)
  31. *    P3              - ASCII data OR
  32. *    P6              - raw binary data
  33. *    # hello         - optional comment(s)
  34. *    wwww hhhh       - Width, Height (ASCII text)
  35. *    # world         - optional comment(s)
  36. *    nnn             - maximum color (nnn = bright, 0 = black)
  37. *
  38. *  (each pixel: one of the following)
  39. *    rr gg bb        - Red, green, blue of intensity 0-nnn (binary byte)
  40. *    RRR GGG BBB     - Red, green, blue of intensity 0-nnn (ASCII number)
  41. *
  42. *****************************************************************************/
  43.  
  44. #include "frame.h"
  45. #include "povproto.h"
  46. #include "povray.h"
  47. #include "optout.h"
  48. #include "pgm.h"
  49. #include "ppm.h"
  50.  
  51. /*****************************************************************************
  52. * Local preprocessor defines
  53. ******************************************************************************/
  54.  
  55. /*****************************************************************************
  56. * Local typedefs
  57. ******************************************************************************/
  58.  
  59. /*****************************************************************************
  60. * Local variables
  61. ******************************************************************************/
  62.  
  63. static int PPM_Line_Number;
  64.  
  65. /*****************************************************************************
  66. * Static functions
  67. ******************************************************************************/
  68.  
  69. static int Open_PPM_File PARAMS ((FILE_HANDLE *handle, char *name, int *width,
  70.                   int *height, int buffer_size, int mode));
  71. static void Write_PPM_Line PARAMS ((FILE_HANDLE *handle, COLOUR *line_data,
  72.                     int line_number));
  73. static int Read_PPM_Line PARAMS((FILE_HANDLE *handle, COLOUR *line_data,
  74.                  int *line_number));
  75. static void Close_PPM_File PARAMS((FILE_HANDLE *handle));
  76.  
  77. /*****************************************************************************
  78. *
  79. * FUNCTION
  80. *
  81. * INPUT
  82. *
  83. * OUTPUT
  84. *
  85. * RETURNS
  86. *
  87. * AUTHOR
  88. *
  89. * DESCRIPTION
  90. *
  91. * CHANGES
  92. *
  93. ******************************************************************************/
  94.  
  95. FILE_HANDLE *Get_PPM_File_Handle()
  96. {
  97.   FILE_HANDLE *handle;
  98.  
  99.   handle = (FILE_HANDLE *) POV_MALLOC(sizeof(FILE_HANDLE), "PPM file handle") ;
  100.  
  101.   handle->Open_File_p = Open_PPM_File;
  102.   handle->Write_Line_p = Write_PPM_Line;
  103.   handle->Read_Line_p = Read_PPM_Line;
  104.   handle->Read_Image_p = Read_PPM_Image;
  105.   handle->Close_File_p = Close_PPM_File;
  106.  
  107.   handle->file = NULL;
  108.   handle->buffer = NULL;
  109.   handle->buffer_size = 0;
  110.  
  111.   return (handle);
  112. }
  113.  
  114. /*****************************************************************************
  115. *
  116. * FUNCTION
  117. *
  118. * INPUT
  119. *   
  120. * OUTPUT
  121. *   
  122. * RETURNS
  123. *   
  124. * AUTHOR
  125. *   
  126. * DESCRIPTION
  127. *
  128. * CHANGES
  129. *
  130. ******************************************************************************/
  131.  
  132. static int Open_PPM_File(handle, name, width, height, buffer_size, mode)
  133. FILE_HANDLE *handle;
  134. char *name;
  135. int *width;
  136. int *height;
  137. int buffer_size;
  138. int mode;
  139. {
  140.   char type;
  141.   int input;
  142.   char junk[512];
  143.  
  144.   handle->mode = mode;
  145.   handle->filename = name;
  146.   PPM_Line_Number = 0;
  147.  
  148.   switch (mode)
  149.   {
  150.     case READ_MODE:
  151.  
  152.       if ((handle->file = fopen(name, READ_FILE_STRING)) == NULL)
  153.       {
  154.         return(0);
  155.       }
  156.  
  157.       if (buffer_size != 0)
  158.       {
  159.         handle->buffer = POV_MALLOC((size_t)buffer_size, "PPM file buffer") ;
  160.         setvbuf(handle->file, handle->buffer, _IOFBF, buffer_size);
  161.       }
  162.  
  163.       if (fscanf(handle->file, "P%c\n", &type) != 1 || type != '6')
  164.       {
  165.         return(0);
  166.       }
  167.  
  168.       /* Ignore any comments (if they are written) */
  169.  
  170.       while ((input = fgetc(handle->file)) == '#')
  171.       {
  172.         fgets(junk, 512, handle->file);
  173.       }
  174.  
  175.       ungetc(input, handle->file);
  176.  
  177.       if (fscanf(handle->file, "%d %d\n255\n", width, height) != 2)
  178.       {
  179.         return(0);
  180.       }
  181.  
  182.       handle->width = *width;
  183.       handle->height = *height;
  184.       handle->buffer_size = buffer_size;
  185.  
  186.       break;
  187.  
  188.     case WRITE_MODE:
  189.  
  190.       if (!strcmp(name, "-"))
  191.       {
  192.         buffer_size = 0;
  193.         handle->file = stdout;
  194.       }
  195.       else
  196.       {
  197.         if ((handle->file = fopen(name, WRITE_FILE_STRING)) == NULL)
  198.         {
  199.           return(0);
  200.         }
  201.       }
  202.  
  203.       if (buffer_size != 0)
  204.       {
  205.         handle->buffer = POV_MALLOC((size_t)buffer_size, "PPM file buffer") ;
  206.         setvbuf(handle->file, handle->buffer, _IOFBF, buffer_size);
  207.       }
  208.  
  209.       fprintf(handle->file, "P6\n");
  210.  
  211. #ifdef POV_COMMENTS
  212. #ifdef TRACER
  213.       fprintf(handle->file, "# Author: %s\n", TRACER);
  214. #endif
  215.  
  216.       fprintf(handle->file, "# Source: Persistence of Vision(tm) Ray Tracer v%s%s\n",
  217.               POV_RAY_VERSION, COMPILER_VER);
  218.  
  219.       if (strcmp(opts.Input_File_Name, "-"))
  220.       {
  221.         fprintf(handle->file, "# Input File: %s\n", opts.Input_File_Name);
  222.       }
  223.  
  224.       if (opts.FrameSeq.Clock_Value != 0)
  225.       {
  226.         fprintf(handle->file, "# POV Clock: %g\n", opts.FrameSeq.Clock_Value);
  227.       }
  228.  
  229.       if (opts.Quality != 9)
  230.       {
  231.         fprintf(handle->file, "# Rendering Quality: %d\n", opts.Quality);
  232.       }
  233. #endif /* POV_COMMENTS */
  234.  
  235.       fprintf(handle->file, "%d %d\n255\n", *width, *height);
  236.  
  237.       handle->width = *width;
  238.       handle->height = *height;
  239.  
  240.       handle->buffer_size = buffer_size;
  241.  
  242.       break;
  243.  
  244.     case APPEND_MODE:
  245.  
  246.       if (!strcmp(name, "-"))
  247.       {
  248.         buffer_size = 0;
  249.         handle->file = stdout;
  250.       }
  251.       else
  252.       {
  253.         if ((handle->file = fopen(name, APPEND_FILE_STRING)) == NULL)
  254.         {
  255.           return(0);
  256.         }
  257.       }
  258.  
  259.       if (buffer_size != 0)
  260.       {
  261.         handle->buffer = POV_MALLOC((size_t)buffer_size, "PPM file buffer") ;
  262.         setvbuf(handle->file, handle->buffer, _IOFBF, buffer_size);
  263.       }
  264.  
  265.       handle->buffer_size = buffer_size;
  266.  
  267.       break;
  268.   }
  269.  
  270.   return(1);
  271. }
  272.  
  273. /*****************************************************************************
  274. *
  275. * FUNCTION
  276. *
  277. * INPUT
  278. *
  279. * OUTPUT
  280. *
  281. * RETURNS
  282. *
  283. * AUTHOR
  284. *   
  285. * DESCRIPTION
  286. *
  287. * CHANGES
  288. *
  289. ******************************************************************************/
  290.  
  291. static void Write_PPM_Line(handle, line_data, line_number)
  292. FILE_HANDLE *handle;
  293. COLOUR *line_data;
  294. int line_number;
  295. {
  296.   unsigned int gray;
  297.   register int x;
  298.  
  299.   for (x = 0 ; x < handle->width ; x++)
  300.   {
  301.     if (opts.Options & HF_GRAY_16)  /* 16 bit grayscale output */
  302.     {
  303.       gray = ((0.30 * line_data[x][RED]) +
  304.               (0.59 * line_data[x][GREEN]) +
  305.               (0.11 * line_data[x][BLUE])) * 65535;
  306.  
  307.       if ((putc((gray >> 8) & 0xFF, handle->file) == EOF) ||
  308.           (putc(gray & 0xFF, handle->file) == EOF) ||
  309.           (putc(0, handle->file) == EOF))
  310.       {
  311.         Error("Error writing PPM output data to %s.\n",handle->filename);
  312.       }
  313.     }
  314.     else                            /* Normal 24 bit pixel coloring */
  315.     {
  316.       if ((putc((int)floor(line_data[x][RED] * 255.0), handle->file) == EOF) ||
  317.           (putc((int)floor(line_data[x][GREEN]*255.0), handle->file) == EOF) ||
  318.           (putc((int)floor(line_data[x][BLUE]*255.0), handle->file) == EOF))
  319.       {
  320.         Error("Error writing PPM output data to %s.\n",handle->filename);
  321.       }
  322.     }
  323.   }
  324.  
  325.   PPM_Line_Number++;
  326.  
  327.   if (handle->buffer_size == 0)
  328.   {
  329.     /* close and reopen file for integrity in case we crash */
  330.  
  331.     fflush(handle->file);
  332.  
  333.     if (strcmp(handle->filename, "-"))
  334.     {
  335.       handle->file = freopen(handle->filename,APPEND_FILE_STRING,handle->file);
  336.     }
  337.   }
  338. }
  339.  
  340. /*****************************************************************************
  341. *
  342. * FUNCTION
  343. *
  344. * INPUT
  345. *
  346. * OUTPUT
  347. *
  348. * RETURNS
  349. *
  350. * AUTHOR
  351. *
  352. * DESCRIPTION
  353. *
  354. * CHANGES
  355. *
  356. ******************************************************************************/
  357.  
  358. static int Read_PPM_Line(handle, line_data, line_number)
  359. FILE_HANDLE *handle;
  360. COLOUR *line_data;
  361. int *line_number;
  362. {
  363.   int data, i;
  364.  
  365.   if ((data = getc(handle->file)) == EOF)
  366.   {
  367.     return (0);
  368.   }
  369.  
  370.   ungetc(data, handle->file);
  371.  
  372.   *line_number = PPM_Line_Number++;
  373.  
  374.   for (i = 0 ; i < handle->width ; i++)
  375.   {
  376.     if ((data = getc(handle->file)) == EOF)
  377.     {
  378.       return(-1);
  379.     }
  380.  
  381.     line_data[i][RED] = (DBL) data / 255.0;
  382.  
  383.     if ((data = getc(handle->file)) == EOF)
  384.     {
  385.       return(-1);
  386.     }
  387.  
  388.     line_data[i][GREEN] = (DBL) data / 255.0;
  389.  
  390.     if ((data = getc(handle->file)) == EOF)
  391.     {
  392.       return(-1);
  393.     }
  394.  
  395.     line_data[i][BLUE] = (DBL) data / 255.0;
  396.   }
  397.  
  398.   return (1);
  399. }
  400.  
  401. /*****************************************************************************
  402. *
  403. * FUNCTION
  404. *
  405. * INPUT
  406. *
  407. * OUTPUT
  408. *
  409. * RETURNS
  410. *
  411. * AUTHOR
  412. *
  413. * DESCRIPTION
  414. *
  415. * CHANGES
  416. *
  417. ******************************************************************************/
  418.  
  419. static void Close_PPM_File(handle)
  420. FILE_HANDLE *handle;
  421. {
  422.   if (handle->file)
  423.   {
  424.     fflush(handle->file);
  425.     fclose(handle->file);
  426.   }
  427.  
  428.   if (handle->buffer != NULL)
  429.   {
  430.     POV_FREE(handle->buffer);
  431.   }
  432.  
  433.   handle->file = NULL;
  434.   handle->buffer = NULL;
  435. }
  436.  
  437. /*****************************************************************************
  438. *
  439. * FUNCTION
  440. *
  441. * INPUT
  442. *
  443. * OUTPUT
  444. *
  445. * RETURNS
  446. *
  447. * AUTHOR
  448. *
  449. * DESCRIPTION
  450. *
  451. * CHANGES
  452. *
  453. ******************************************************************************/
  454.  
  455. void Read_PPM_Image(Image, name)
  456. IMAGE *Image;
  457. char *name;
  458. {
  459.   char type;
  460.   int width, height;
  461.   int depth;
  462.   char input;
  463.   char junk[512];
  464.   int x, y;
  465.   int data;
  466.   IMAGE_LINE *line_data;
  467.   FILE *infile;
  468.  
  469.   if ((infile = Locate_File(name, READ_FILE_STRING, ".ppm", ".PPM",TRUE)) == NULL)
  470.   {
  471.     Error("Error opening PPM image %s.\n", name);
  472.   }
  473.  
  474.   if (fscanf(infile, "P%c\n", &type) != 1 || (type != '3' && type != '6'))
  475.   {
  476.     Error ("File is not in PPM format.\n", name);
  477.   }
  478.  
  479.   /* Ignore any comments */
  480.  
  481.   while ((input = fgetc(infile)) == '#')
  482.   {
  483.     fgets(junk, 512, infile);
  484.   }
  485.  
  486.   ungetc(input, infile);
  487.  
  488.   if (fscanf(infile, "%d %d\n", &width, &height) != 2)
  489.   {
  490.     Error ("Error reading width or height from PPM image.\n", name);
  491.   }
  492.  
  493.   /* Ignore any comments */
  494.   while ((input = fgetc(infile)) == '#')
  495.   {
  496.     fgets(junk, 512, infile);
  497.   }
  498.  
  499.   ungetc(input, infile);
  500.  
  501.   if (fscanf(infile, "%d\n", &depth) != 1 || depth > 255 || depth < 1)
  502.   {
  503.     Error ("Unsupported number of colors (%d) in PPM image.\n", depth);
  504.   }
  505.  
  506.   Image->width  = (DBL)(Image->iwidth = width);
  507.   Image->height = (DBL)(Image->iheight = height);
  508.  
  509.   Image->Colour_Map_Size = 0;
  510.  
  511.   Image->Colour_Map = NULL;
  512.  
  513.   Image->data.rgb_lines = (IMAGE_LINE *) POV_MALLOC(Image->iheight * sizeof (IMAGE_LINE), "PPM image");
  514.  
  515.   for (y = 0; y < height; y++)
  516.   {
  517.     line_data = &Image->data.rgb_lines[y];
  518.  
  519.     line_data->red   = (unsigned char *)POV_MALLOC(width,"PPM image line");
  520.     line_data->green = (unsigned char *)POV_MALLOC(width,"PPM image line");
  521.     line_data->blue  = (unsigned char *)POV_MALLOC(width,"PPM image line");
  522.     line_data->transm = (unsigned char *)NULL;
  523.  
  524.     if (type == '3') /* ASCII data to be input */
  525.     {
  526.       for (x = 0; x < width; x++)
  527.       {
  528.         if (fscanf(infile,"%d",&data) != 1)
  529.         {
  530.           Error("Error reading data from PPM image.\n");
  531.         }
  532.  
  533.         line_data->red[x] = data*255/depth;
  534.  
  535.         if (fscanf(infile,"%d",&data) != 1)
  536.         {
  537.           Error("Error reading data from PPM image.\n");
  538.         }
  539.  
  540.         line_data->green[x] = data*255/depth;
  541.  
  542.         if (fscanf(infile,"%d",&data) != 1)
  543.         {
  544.           Error("Error reading data from PPM image.\n");
  545.         }
  546.  
  547.         line_data->blue[x] = data*255/depth;
  548.       }
  549.     }
  550.     else /* (type == '6') Raw binary data to be input */
  551.     {
  552.       for (x = 0; x < width; x++)
  553.       {
  554.         if ((data = getc(infile)) == EOF)
  555.         {
  556.           Error("Error reading data from PPM image.\n");
  557.         }
  558.  
  559.         line_data->red[x] = data*255/depth;
  560.  
  561.         if ((data = getc(infile)) == EOF)
  562.         {
  563.           Error("Error reading data from PPM image.\n");
  564.         }
  565.  
  566.         line_data->green[x] = data*255/depth;
  567.  
  568.         if ((data = getc(infile)) == EOF)
  569.         {
  570.           Error("Error reading data from PPM image.\n");
  571.         }
  572.  
  573.         line_data->blue[x] = data*255/depth;
  574.       }
  575.     }
  576.   }
  577.  
  578.   fclose(infile);
  579. }
  580.